﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
using DevExpress.XtraEditors;
using log4net;
using McsUtility;

namespace MinerManager
{
	public partial class Main : DevExpress.XtraEditors.XtraForm
	{
		ILog logger = LogManager.GetLogger(typeof(Program));
		private Common.AgentComponent Agent = new Common.AgentComponent();

		private Forms.UserLogin FormLogin = null;//用户登录窗体
		private Forms.Reconnect FormReconnect = null;//掉线重连窗体

		private ContextMenuStrip RightContextMenu = null;//右键菜单

		private int TotalCount = 0;//数据总量
		private int PageIndex = 1;//页码
		private int PageSize = 20;//显示数量
		private int PageCount = 1;//总页码

		private bool AllowRefreshHashrate = true;//是否允许刷新算力
		private bool TimerRefreshingHashrate = false;//计时器正在刷新算力
		private bool WaterfallRequestingMinerList = false;//是否正在瀑布请求矿机列表
		private List<int> DeleteMinerIds = new List<int>();//执行删除矿机操作的矿机Id

		public Main()
		{
			InitializeComponent();
		}

		#region 窗体事件

		private void Main_Load(object sender, EventArgs e)
		{
			this.Text = Utility.SoftName;
			SetControlStatus(false);//未登录
			InitAgent();
			LoadContextMenu();
			ItemDisplayLog_CheckedChanged(this, null);

			BottomStatus_Timer.Caption = "时间：" + DateTime.Now.ToString("yyyy年MM月dd日 HH:mm");
			BottomStatus_Message.Caption = "请先登录系统后再进行相关操作";
			WriteStatusVersionMessage();

			#region 矿机状态

			List<ComboboxListItem> items = new List<ComboboxListItem>
			{
				new ComboboxListItem("全部", "-1"),
				new ComboboxListItem("挖矿中", "2"),
				new ComboboxListItem("在线", "1"),
				new ComboboxListItem("离线", "0")
			};
			Utility.Forms.SetComboBoxEdit(this, "SearchStatus", items);

			#endregion

			#region 状态栏时间

			Action<object, EventArgs> statusTick = delegate (object obj, EventArgs args)
			{
				BottomStatus_Timer.Caption = "时间：" + DateTime.Now.ToString("yyyy年MM月dd日 HH:mm");
			};
			Timer statusTimer = new Timer
			{
				Interval = 1000,
				Enabled = true
			};
			statusTimer.Tick += new EventHandler(statusTick);
			statusTimer.Start();

			#endregion

			#region 自动登录

			if (System.IO.File.Exists(Utility.AutoLoginPath))
			{
				string autoLoginString = System.IO.File.ReadAllText(Utility.AutoLoginPath, Encoding.UTF8);
				if (!string.IsNullOrWhiteSpace(autoLoginString))
				{
					//连接服务器
					Common.ConnectionServer conn = new Common.ConnectionServer(this.Agent);
					conn.Connection();

					//发送数据
					if (this.Agent.IsStarted)
					{
						Common.Data.LoginUserName = autoLoginString.Split(',')[0];
						Common.Data.LoginPassWord = autoLoginString.Split(',')[1];

						McsUtility.Models.LoginModel info = new McsUtility.Models.LoginModel
						{
							LoginName = Common.Data.LoginUserName,
							LoginPass = Common.Data.LoginPassWord
						};
						byte[] bytes = ProtocolHelper.WritePackage<McsUtility.Models.LoginModel>(ProtoType.MinerManagerLogin, info);
						this.Agent.AgentSend(bytes);
					}
					else
					{
						MessageBox.Show("服务器连接已断开，请检查网络是否畅通后重新登录。", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
						WriteStatusMessage("服务器连接已断开，请检查网络是否畅通后重新登录。");
					}
				}
			}

			#endregion

			#region 矿机状态日志

			if (System.IO.File.Exists(Utility.MinerStatusLogPath))
			{
				string minerStatusLog = System.IO.File.ReadAllText(Utility.MinerStatusLogPath, Encoding.UTF8);
				MinerStatusLog.Text = minerStatusLog;
			}

			#endregion

			#region 刷新矿机算力
			
			Action<object, EventArgs> refreshHashrateTick = delegate (object obj, EventArgs args)
			{
				//发送数据
				if (this.Agent.IsStarted && this.AllowRefreshHashrate)
				{
					//是否正在刷新算力，正在刷新时终止执行
					if (!this.TimerRefreshingHashrate)
						this.TimerRefreshingHashrate = true;
					else
						return;

					RequestMinerHashrate();
				}
			};
			Timer refreshHashrateTimer = new Timer
			{
				Interval = 1000 * 5,
				Enabled = true
			};
			refreshHashrateTimer.Tick += new EventHandler(refreshHashrateTick);
			refreshHashrateTimer.Start();

			#endregion
		}

		private void Main_SizeChanged(object sender, EventArgs e)
		{
			WaterfallRequestMinerList();
		}

		private void Main_FormClosing(object sender, FormClosingEventArgs e)
		{
			if (this.Agent.IsStarted)
			{
				this.Agent.OnShutdown -= new EventHandler<EventArgs>(Agent_OnShutdown);
				this.Agent.Stop();
			}
		}

		#endregion

		#region void LoadContextMenu() 加载MinerList右键菜单。

		/// <summary>
		/// 加载MinerList右键菜单。
		/// </summary>
		private void LoadContextMenu()
		{
			this.RightContextMenu = new ContextMenuStrip();

			#region 复制

			Action<object, EventArgs> copyClick = delegate (object obj, EventArgs args)
			{
				string value = MinerListGridView.GetFocusedRowCellValue(MinerListGridView.FocusedColumn).ToString();
				Clipboard.SetDataObject(value);
			};

			ToolStripMenuItem itemCopy = new ToolStripMenuItem("复制");
			itemCopy.Click += new EventHandler(copyClick);
			this.RightContextMenu.Items.Add(itemCopy);

			#endregion

			#region 矿机信息

			Action<object, EventArgs> hashrateClick = delegate (object obj, EventArgs args)
			{
				if (this.Agent.IsStarted)
				{
					int[] selectedRows = MinerListGridView.GetSelectedRows();
					int selectedIndex = selectedRows.Length > 0 ? selectedRows[0] : -1;
					if (selectedIndex >= 0)
					{
						List<Models.MinerModel> infosMiner = MinerList.DataSource as List<Models.MinerModel>;
						if (infosMiner.Count > 0)
						{
							Action<object, EventArgs> onClose = delegate (object closeObj, EventArgs closeArgs)
							{
								this.AllowRefreshHashrate = true;
							};

							this.AllowRefreshHashrate = false;
							Forms.MinerHashrate form = new Forms.MinerHashrate(this.Agent, infosMiner[selectedIndex].ID, infosMiner[selectedIndex].MinerName, infosMiner[selectedIndex].FirstCoin, infosMiner[selectedIndex].SecondCoin);
							form.OnClose += new EventHandler<EventArgs>(onClose);
							form.ShowDialog();
						}
					}
				}
				else
				{
					MessageBox.Show("服务器连接已断开，请检查网络是否畅通后重新登录。", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
					WriteStatusMessage("服务器连接已断开，请检查网络是否畅通后重新登录。");
				}
			};

			ToolStripMenuItem itemHashrate = new ToolStripMenuItem("矿机信息");
			itemHashrate.Click += new EventHandler(hashrateClick);
			this.RightContextMenu.Items.Add(itemHashrate);

			#endregion

			#region 矿机日志

			Action<object, EventArgs> minerLogClick = delegate (object obj, EventArgs args)
			{
				if (this.Agent.IsStarted)
				{
					int[] selectedRows = MinerListGridView.GetSelectedRows();
					int selectedIndex = selectedRows.Length > 0 ? selectedRows[0] : -1;
					if (selectedIndex >= 0)
					{
						List<Models.MinerModel> infosMiner = MinerList.DataSource as List<Models.MinerModel>;
						if (infosMiner.Count > 0)
						{
							Forms.MinerLog form = new Forms.MinerLog(this.Agent, infosMiner[selectedIndex].ID, infosMiner[selectedIndex].MinerName);
							form.ShowDialog();
						}
					}
				}
				else
				{
					MessageBox.Show("服务器连接已断开，请检查网络是否畅通后重新登录。", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
					WriteStatusMessage("服务器连接已断开，请检查网络是否畅通后重新登录。");
				}
			};

			ToolStripMenuItem itemMinerLog = new ToolStripMenuItem("矿机日志");
			itemMinerLog.Click += new EventHandler(minerLogClick);
			this.RightContextMenu.Items.Add(itemMinerLog);

			#endregion

			#region 开始挖矿事件

			Action<object, EventArgs> startClick = delegate (object obj, EventArgs args)
			{
				if (this.Agent.IsStarted)
				{
					if (MessageBox.Show("确定要开始挖矿吗？", "开始挖矿", MessageBoxButtons.OKCancel, MessageBoxIcon.Question, MessageBoxDefaultButton.Button1) == DialogResult.OK)
					{
						int[] selectedRows = MinerListGridView.GetSelectedRows();
						int selectedIndex = selectedRows.Length > 0 ? selectedRows[0] : -1;
						if (selectedIndex >= 0)
						{
							List<Models.MinerModel> infosMiner = MinerList.DataSource as List<Models.MinerModel>;
							if (infosMiner.Count > 0)
							{
								byte[] bytes = ProtocolHelper.WritePackage<int[]>(ProtoType.MinerManagerStartMining, new int[] { infosMiner[selectedIndex].ID });
								this.Agent.AgentSend(bytes);
								MessageBox.Show("开始挖矿指令下达成功。", "成功", MessageBoxButtons.OK, MessageBoxIcon.Information);
							}
						}
						else
						{
							MessageBox.Show("未获取到有效的选取行信息。", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
						}
					}
				}
				else
				{
					MessageBox.Show("服务器连接已断开，请检查网络是否畅通后重新登录。", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
					WriteStatusMessage("服务器连接已断开，请检查网络是否畅通后重新登录。");
				}
			};

			ToolStripMenuItem itemStart = new ToolStripMenuItem("开始挖矿");
			itemStart.Click += new EventHandler(startClick);
			this.RightContextMenu.Items.Add(itemStart);

			#endregion

			#region 停止挖矿事件

			Action<object, EventArgs> stopClick = delegate (object obj, EventArgs args)
			{
				if (this.Agent.IsStarted)
				{
					if (MessageBox.Show("确定要停止挖矿吗？", "停止挖矿", MessageBoxButtons.OKCancel, MessageBoxIcon.Question, MessageBoxDefaultButton.Button1) == DialogResult.OK)
					{
						int[] selectedRows = MinerListGridView.GetSelectedRows();
						int selectedIndex = selectedRows.Length > 0 ? selectedRows[0] : -1;
						if (selectedIndex >= 0)
						{
							List<Models.MinerModel> infosMiner = MinerList.DataSource as List<Models.MinerModel>;
							if (infosMiner.Count > 0)
							{
								byte[] bytes = ProtocolHelper.WritePackage<int[]>(ProtoType.MinerManagerEndMining, new int[] { infosMiner[selectedIndex].ID });
								this.Agent.AgentSend(bytes);
								MessageBox.Show("停止挖矿指令下达成功。", "成功", MessageBoxButtons.OK, MessageBoxIcon.Information);
							}
						}
						else
						{
							MessageBox.Show("未获取到有效的选取行信息。", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
						}
					}
				}
				else
				{
					MessageBox.Show("服务器连接已断开，请检查网络是否畅通后重新登录。", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
					WriteStatusMessage("服务器连接已断开，请检查网络是否畅通后重新登录。");
				}
			};

			ToolStripMenuItem itemStop = new ToolStripMenuItem("停止挖矿");
			itemStop.Click += new EventHandler(stopClick);
			this.RightContextMenu.Items.Add(itemStop);

			#endregion

			#region 重启矿机事件

			Action<object, EventArgs> restartClick = delegate (object obj, EventArgs args)
			{
				if (MessageBox.Show("确定要重启矿机吗？", "重启矿机", MessageBoxButtons.OKCancel, MessageBoxIcon.Question, MessageBoxDefaultButton.Button1) == DialogResult.OK)
				{
					if (this.Agent.IsStarted)
					{
						int[] selectedRows = MinerListGridView.GetSelectedRows();
						int selectedIndex = selectedRows.Length > 0 ? selectedRows[0] : -1;
						if (selectedIndex >= 0)
						{
							List<Models.MinerModel> infosMiner = MinerList.DataSource as List<Models.MinerModel>;
							if (infosMiner.Count > 0)
							{
								byte[] bytes = ProtocolHelper.WritePackage<int[]>(ProtoType.MinerManagerReset, new int[] { infosMiner[selectedIndex].ID });
								this.Agent.AgentSend(bytes);
								MessageBox.Show("重启矿机指令下达成功。", "成功", MessageBoxButtons.OK, MessageBoxIcon.Information);
							}
						}
						else
						{
							MessageBox.Show("未获取到有效的选取行信息。", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
						}
					}
					else
					{
						MessageBox.Show("服务器连接已断开，请检查网络是否畅通后重新登录。", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
						WriteStatusMessage("服务器连接已断开，请检查网络是否畅通后重新登录。");
					}
				}
			};

			ToolStripMenuItem itemRestart = new ToolStripMenuItem("重启矿机");
			itemRestart.Click += new EventHandler(restartClick);
			this.RightContextMenu.Items.Add(itemRestart);

			#endregion

			#region 高级配置事件

			Action<object, EventArgs> configurationClick = delegate (object obj, EventArgs args)
			{
				if (this.Agent.IsStarted)
				{
					int[] selectedRows = MinerListGridView.GetSelectedRows();
					int selectedIndex = selectedRows.Length > 0 ? selectedRows[0] : -1;
					if (selectedIndex >= 0)
					{
						List<Models.MinerModel> infosMiner = MinerList.DataSource as List<Models.MinerModel>;
						if (infosMiner.Count > 0)
						{
							Action<object, ObjectEventArgs> onSuccess = delegate (object successObj, ObjectEventArgs successArgs)
							{
								if (MessageBox.Show("高级配置指令下达成功。", "成功", MessageBoxButtons.OK, MessageBoxIcon.Information) == DialogResult.OK)
								{
									Forms.MinerConfiguration formConfiguration = successObj as Forms.MinerConfiguration;
									if (formConfiguration != null)
										formConfiguration.Close();
								}
							};

							Forms.MinerConfiguration form = new Forms.MinerConfiguration(this.Agent, infosMiner[selectedIndex]);
							form.OnSuccess += new EventHandler<ObjectEventArgs>(onSuccess);
							form.ShowDialog();
						}
					}
					else
					{
						MessageBox.Show("未获取到有效的选取行信息。", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
					}
				}
				else
				{
					MessageBox.Show("服务器连接已断开，请检查网络是否畅通后重新登录。", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
					WriteStatusMessage("服务器连接已断开，请检查网络是否畅通后重新登录。");
				}
			};

			ToolStripMenuItem itemConfiguration = new ToolStripMenuItem("高级配置");
			itemConfiguration.Click += new EventHandler(configurationClick);
			this.RightContextMenu.Items.Add(itemConfiguration);

			#endregion
		}

		#endregion

		#region void InitAgent() 初始化Agent

		#region void InitAgent()

		private void InitAgent()
		{
			//this.Agent.LocalIp = MyIp();
			//this.Agent.ServerIp = "192.168.1.38";
			//this.Agent.ServerPort = 12345;
			this.Agent.OnMessage += new EventHandler<MsgEventArgs>(Agent_OnMessage);
			this.Agent.OnReceive += new EventHandler<RcvEventArgs>(Agent_OnReceive);
			this.Agent.OnShutdown += new EventHandler<EventArgs>(Agent_OnShutdown);
			this.Agent.OnExceptionClose += new EventHandler<EventArgs>(Agent_OnExceptionClose);

			this.Agent.OnNodeServerMinerManagerGetStaffs += new EventHandler<ByteEventArgs>(Agent_OnNodeServerMinerManagerGetStaffs);
		}

		#endregion

		#region void Agent_OnReceive(object sender, RcvEventArgs e)

		private void Agent_OnReceive(object sender, RcvEventArgs e)
		{
			var proto = ProtocolHelper.GetProtoType(e.Buffer, body: out byte[] body);
			//string json = System.Text.Encoding.UTF8.GetString(body);

			switch (proto)
			{
				case ProtoType.NodeServerManagerLogin://NodeServer回应管理端登录
					ProcessNodeServerManagerLogin(body);
					break;
				case ProtoType.NodeServerManagerGetMiners://NodeServer回应管理端请求的矿机搜索信息
					ProcessNodeServerManagerGetMiners(body);
					break;
				case ProtoType.NodeServerMinerManagerGetRedisData://NodeServer响应管理端请求Redis数据
					ProcessNodeServerMinerManagerGetRedisData(body);
					break;
				case ProtoType.NodeServerMinerLoginToManager://NodeServer下发矿机登录信息给管理端
					ProcessNodeServerMinerLoginToManager(body);
					break;
				case ProtoType.NodeServerMinerLogoutToManager://NodeServer下发矿机离线信息给管理端
					ProcessNodeServerMinerLogoutToManager(body);
					break;
				case ProtoType.MinerClientStartMiningToManager://矿机挖矿状态下发给管理端
					ProcessMinerClientStartMiningToManager(body);
					break;
				case ProtoType.MinerClientEndMiningToManager://矿机停止挖矿状态下发给管理端
					ProcessMinerClientEndMiningToManager(body);
					break;
				case ProtoType.NodeServerMinerManagerDelMiner://删除矿机
					ProcessNodeServerMinerManagerDelMiner(body);
					break;
				case ProtoType.MinerReAccept://NodeServer通知端重连NodeServer
					ProcessMinerReAccept(body);
					break;
				case ProtoType.NodeServerWarnToMinerManager://NodeServer下发报警信息
					ProcessNodeServerWarnToMinerManager(body);
					break;
				case ProtoType.NodeServerManagerGetMinerModel://NodeServer回应管理端请求的矿机搜索信息
					//ProcessNodeServerManagerGetMinerModel(body);
					break;
				case ProtoType.MinerManagerDownToManager://管理端收到指令，断开连接
					ProcessMinerManagerDownToManager();
					break;
				case ProtoType.NodeServerManagerGetMinersAll: //NodeServer回应管理端请求的矿机搜索信息
					ProcessNodeServerManagerGetMinersAll(body);
					break;
			}
		}

		#region void ProcessNodeServerManagerLogin(byte[] body) NodeServer回应管理端登录

		private void ProcessNodeServerManagerLogin(byte[] body)
		{
			//NodeServerManagerLogin = 8 NodeServer回应管理端登录

			McsUtility.Models.ResultModel result = ProtocolHelper.ReadPackageBody<McsUtility.Models.ResultModel>(body);
			if (result.success)
			{
				McsUtility.Models.LoginResultModel info = TomNet.Utility.Data.JsonHelper.FromJson<McsUtility.Models.LoginResultModel>(result.data.ToString());
				Common.Data.Staff = info.Staff;
				Common.Data.UserCurrency = info.Currencys;
				this.FormLogin?.HandleFeedback(true);

				SetControlStatus(true);
				WriteStatusLoginMessage("登录用户：" + info.Name);

				//更新登录状态
				Common.Data.IsLogin = true;

				//无客户经理时请求客户经理列表
				if (info.Staff.ID <= 0)
				{
					byte[] bytes = ProtocolHelper.WritePackage(ProtoType.MinerManagerGetStaffs, "");
					this.Agent.AgentSend(bytes);
				}
			}
			else
			{
				//更新登录状态
				Common.Data.IsLogin = false;

				ProcessNodeServerManagerLoginFailureHandle();
			}
		}

		private delegate void DelegateProcessNodeServerManagerLoginFailureHandle();
		private void ProcessNodeServerManagerLoginFailureHandle()
		{
			if (this.InvokeRequired)
			{
				DelegateProcessNodeServerManagerLoginFailureHandle d = new DelegateProcessNodeServerManagerLoginFailureHandle(ProcessNodeServerManagerLoginFailureHandle);
				this.BeginInvoke(d);
			}
			else
			{
				bool loginWindowIsOpen = false;//登录窗体是否处于打开状态
				foreach (Form form in Application.OpenForms)
				{
					if (form.Name.Equals("UserLogin", StringComparison.CurrentCultureIgnoreCase))
					{
						loginWindowIsOpen = true;
						break;
					}
				}

				if (!loginWindowIsOpen)
					MessageBox.Show("登录失败，请检查登录账号和密码是否正确。", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
				else
					this.FormLogin?.HandleFeedback(false);

				SetControlStatus(false);
			}
		}

		#endregion

		#region void ProcessNodeServerManagerGetMiners(byte[] body) NodeServer回应管理端请求的矿机搜索信息

		private void ProcessNodeServerManagerGetMiners(byte[] body)
		{
			//NodeServerManagerGetMiners = 29 NodeServer回应管理端请求的矿机搜索信息
			if (body != null)
			{
				McsUtility.Models.MinersResponseModel result = ProtoBufHelper.Deserialize<McsUtility.Models.MinersResponseModel>(body);
				if (result != null && result.Miners != null)
				{
					this.TotalCount = result.TotalRows;
					this.PageCount = result.TotalRows % this.PageSize > 0 ? result.TotalRows / this.PageSize + 1 : result.TotalRows / this.PageSize;

					List<Models.MinerModel> infos = new List<Models.MinerModel>();
					result.Miners.ForEach(info =>
					{
						infos.Add(info.ConvertMinerModel());
					});
					InsertMinerList(infos);
					RequestMinerHashrate();
				}
			}

			//设置未执行瀑布请求矿机列表
			this.WaterfallRequestingMinerList = false;
		}

		#endregion

		#region void ProcessNodeServerMinerManagerGetRedisData(byte[] body) NodeServer响应管理端请求Redis数据

		private void ProcessNodeServerMinerManagerGetRedisData(byte[] body)
		{
			//NodeServerMinerManagerGetRedisData = 54 NodeServer响应管理端请求Redis数据

			//允许刷新算力时执行
			if (this.AllowRefreshHashrate)
			{
				List<McsUtility.Models.RedisDataModel> result = ProtocolHelper.ReadPackageBody<List<McsUtility.Models.RedisDataModel>>(body);
				LoadMinerHashrate(result);
			}
		}

		#endregion

		#region void ProcessNodeServerMinerLoginToManager(byte[] body) NodeServer下发矿机登录信息给管理端

		private void ProcessNodeServerMinerLoginToManager(byte[] body)
		{
			//NodeServerMinerLoginToManager = 56 NodeServer下发矿机登录信息给管理端

			McsUtility.Models.MinerCloseModel result = ProtocolHelper.ReadPackageBody<McsUtility.Models.MinerCloseModel>(body);
			WriteMinerStatusLog(DateTime.Now, string.Format("矿机“{0}”登录。", result.MinerName));

			UpdateMinerState(result.MinerID, 1);
		}

		#endregion

		#region void ProcessNodeServerMinerLogoutToManager(byte[] body) NodeServer下发矿机离线信息给管理端

		private void ProcessNodeServerMinerLogoutToManager(byte[] body)
		{
			//NodeServerMinerLogoutToManager = 58 NodeServer下发矿机离线信息给管理端

			McsUtility.Models.MinerCloseModel result = ProtocolHelper.ReadPackageBody<McsUtility.Models.MinerCloseModel>(body);
			WriteMinerStatusLog(DateTime.Now, string.Format("矿机“{0}”离线。", result.MinerName));
			UpdateMinerState(result.MinerID, 0);
		}

		#endregion

		#region void ProcessMinerClientStartMiningToManager(byte[] body) 矿机挖矿状态下发给管理端

		private void ProcessMinerClientStartMiningToManager(byte[] body)
		{
			//MinerClientStartMiningToManager = 61 矿机挖矿状态下发给管理端

			McsUtility.Models.MinerClientStatusModel result = ProtocolHelper.ReadPackageBody<McsUtility.Models.MinerClientStatusModel>(body);
			WriteMinerStatusLog(DateTime.Now, string.Format("矿机“{0}”开始挖矿。", result.MinerName));

			result.Model.State = 2;
			UpdateMinerModel(result.MinerId, result.Model.ConvertMinerModel());
		}

		#endregion

		#region void ProcessMinerClientEndMiningToManager(byte[] body) 矿机停止挖矿状态下发给管理端

		private void ProcessMinerClientEndMiningToManager(byte[] body)
		{
			//MinerClientEndMiningToManager = 70 矿机停止挖矿状态下发给管理端

			McsUtility.Models.MinerCloseModel result = ProtocolHelper.ReadPackageBody<McsUtility.Models.MinerCloseModel>(body);
			WriteMinerStatusLog(DateTime.Now, string.Format("矿机“{0}”停止挖矿。", result.MinerName));
			UpdateMinerState(result.MinerID, 1);
		}

		#endregion

		#region void ProcessNodeServerMinerManagerDelMiner(byte[] body) 删除矿机

		private void ProcessNodeServerMinerManagerDelMiner(byte[] body)
		{
			//NodeServerMinerManagerDelMiner = 74 删除矿机

			DeleteMinerModel(this.DeleteMinerIds);
		}

		#endregion

		#region void ProcessMinerReAccept(byte[] body) NodeServer通知端重连NodeServer

		private void ProcessMinerReAccept(byte[] body)
		{
			//MinerReAccept = 52 NodeServer通知端重连NodeServer

			//关闭连接
			this.Agent.Stop();

			McsUtility.Models.GetNodeServerResponseModel result = ProtocolHelper.ReadPackageBody<McsUtility.Models.GetNodeServerResponseModel>(body);

			//连接服务器
			Common.ConnectionServer conn = new Common.ConnectionServer(this.Agent);
			bool isStarted = conn.Connection(result.IP, (ushort)result.Port);
			if (isStarted)
			{
				McsUtility.Models.LoginModel info = new McsUtility.Models.LoginModel
				{
					LoginName = Common.Data.LoginUserName,
					LoginPass = Common.Data.LoginPassWord
				};
				byte[] bytes = ProtocolHelper.WritePackage<McsUtility.Models.LoginModel>(ProtoType.MinerManagerLogin, info);
				this.Agent.AgentSend(bytes);
			}
			else
			{
				MessageBox.Show("服务器连接已断开，请检查网络是否畅通后重新登录。", "连接失败", MessageBoxButtons.OK, MessageBoxIcon.Error);
			}
		}

		#endregion

		#region void ProcessNodeServerWarnToMinerManager(byte[] body) NodeServer下发报警信息

		private void ProcessNodeServerWarnToMinerManager(byte[] body)
		{
			//NodeServerWarnToMinerManager = 88 NodeServer下发报警信息

			McsUtility.Models.WarnModel result = ProtocolHelper.ReadPackageBody<McsUtility.Models.WarnModel>(body);
			WarnPopup(result);
		}

		private delegate void DelegateWarnPopup(McsUtility.Models.WarnModel info);

		private void WarnPopup(McsUtility.Models.WarnModel info)
		{
			if (this.InvokeRequired)
			{
				DelegateWarnPopup d = new DelegateWarnPopup(WarnPopup);
				this.BeginInvoke(d, info);
			}
			else
			{
				string warnMessage = string.Empty;
				string logMessage = string.Empty;

				//Action<object, EventArgs> onShowClick = delegate (object obj, EventArgs args)
				//{
				//	byte[] sendBytes = ProtocolHelper.WritePackage(ProtoType.MinerManagerGetMinerModel, TomNet.Utility.Data.JsonHelper.ToJson(info.MinerID));
				//	this.Agent.AgentSend(sendBytes);

				//	//if (form != null)
				//	//	form.Close();
				//};

				switch (info.WarnType)
				{
					case 0://高温报警
						logMessage = "矿机“" + info.MinerName + "”高温报警：" + info.WarnMessage;
						warnMessage = "矿机“" + info.MinerName + "”高温报警。" + Environment.NewLine + info.WarnMessage;
						OpenPopup("矿机温度过高报警", warnMessage);
						//form = new Forms.FrmPopup("异常报警", "矿机温度过高报警", warnMessage, 60 * 3);
						//form.SetButton(true, "查看矿机", onShowClick);
						//form.Show();
						break;
					case 1://低算力报警
						logMessage = "矿机“" + info.MinerName + "”低算力报警：" + info.WarnMessage;
						warnMessage = "矿机“" + info.MinerName + "”低算力报警。" + Environment.NewLine + info.WarnMessage;
						OpenPopup("矿机算力过低报警", warnMessage);
						//form = new Forms.FrmPopup("异常报警", "矿机算力过低报警", warnMessage, 60 * 3);
						//form.SetButton(true, "查看矿机", onShowClick);
						//form.Show();
						break;
				}

				//写入日志
				if (!string.IsNullOrWhiteSpace(logMessage))
					WriteMinerStatusLog(DateTime.Now, logMessage);
			}
		}

		#endregion

		#region void ProcessNodeServerManagerGetMinerModel(byte[] body) NodeServer回应管理端请求的矿机搜索信息

		//private void ProcessNodeServerManagerGetMinerModel(byte[] body)
		//{
		//	//NodeServerManagerGetMinerModel = 90 NodeServer回应管理端请求的矿机搜索信息

		//	if (body != null)
		//	{
		//		McsUtility.Models.MinersModel info = ProtoBufHelper.Deserialize<McsUtility.Models.MinersModel>(body);
		//		if (info != null)
		//		{
		//			//InsertMinerList(new List<McsUtility.Models.MinersModel> { info });
		//			//this.AllowRefreshHashrate = true;
		//		}
		//	}
		//}

		#endregion

		#region void ProcessMinerManagerDownToManager() 管理端收到指令，断开连接

		private delegate void DelegateProcessMinerManagerDownToManager();

		private void ProcessMinerManagerDownToManager()
		{
			if (this.InvokeRequired)
			{
				DelegateProcessMinerManagerDownToManager d = new DelegateProcessMinerManagerDownToManager(ProcessMinerManagerDownToManager);
				this.BeginInvoke(d);
			}
			else
			{
				this.Agent.Stop();

				//更新登录状态
				Common.Data.IsLogin = false;

				string msg = "您的账号在另一地点登录，您被迫下线。" + Environment.NewLine + Environment.NewLine
					+ "如果这不是您本人的操作，那么您的密码很可能已经泄漏。建议您修改密码。";

				OpenPopup("强制下线", msg);
			}
		}

		#endregion

		#region void ProcessNodeServerManagerGetMinersAll(byte[] body) NodeServer回应管理端请求的矿机搜索信息

		private void ProcessNodeServerManagerGetMinersAll(byte[] body)
		{
			//NodeServerManagerGetMinersAll = 99 NodeServer回应管理端请求的矿机搜索信息

			if (body != null)
			{
				McsUtility.Models.MinersResponseModel result = ProtoBufHelper.Deserialize<McsUtility.Models.MinersResponseModel>(body);
				if (result != null && result.Miners != null)
				{
					this.TotalCount = result.TotalRows;
					this.PageCount = result.TotalRows % this.PageSize > 0 ? result.TotalRows / this.PageSize + 1 : result.TotalRows / this.PageSize;

					List<Models.MinerModel> infos = new List<Models.MinerModel>();
					result.Miners.ForEach(info =>
					{
						infos.Add(info.ConvertMinerModel());
					});
					LoadMinerList(infos);
					RequestMinerHashrate();
				}
			}
		}

		#endregion

		#endregion

		#region void Agent_OnNodeServerMinerManagerGetStaffs(byte[] body)

		private void Agent_OnNodeServerMinerManagerGetStaffs(object sender, ByteEventArgs e)
		{
			List<McsUtility.Models.StaffModel> infosStaff = ProtocolHelper.ReadPackageBody<List<McsUtility.Models.StaffModel>>(e.Bytes);

			//获取默认客户经理
			string staffId = System.Configuration.ConfigurationManager.AppSettings["StaffId"];
			if (string.IsNullOrWhiteSpace(staffId))
				staffId = "2";

			int index = infosStaff.FindIndex(p => p.ID.ToString() == staffId);
			if (index >= 0)
			{
				Common.Data.Staff = infosStaff[index];
				WriteStatusVersionMessage();
			}
		}

		#endregion

		#region void Agent_OnExceptionClose(object sender,EventArgs e)

		private void Agent_OnExceptionClose(object sender, EventArgs e)
		{
			if (Common.Data.IsLogin)
				OpenFormReconnect();

			//更新登录状态
			Common.Data.IsLogin = false;

			Common.Data.UserCurrency = new List<McsUtility.Models.CurrencysModel>();

			ClearSearchData();
			ClearMinerList();
			SetControlStatus(false);
		}

		#endregion

		#region void Agent_OnShutdown(object sender, EventArgs e)

		private void Agent_OnShutdown(object sender, EventArgs e)
		{
			//更新登录状态
			Common.Data.IsLogin = false;

			Common.Data.UserCurrency = new List<McsUtility.Models.CurrencysModel>();

			SetControlStatus(false);
		}

		#endregion

		private void Agent_OnMessage(object sender, MsgEventArgs e)
		{
			System.Diagnostics.Debug.WriteLine(e.Message);
		}

		#endregion

		#region TopMenu按钮点击事件

		private void TopMenu_User_Register_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
		{
			Forms.UserRegister form = new Forms.UserRegister(this.Agent);
			form.ShowDialog();
		}

		#region void TopMenu_User_Login_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)

		private void TopMenu_User_Login_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
		{
			#region onHandle事件

			Action<object, LoginHandleEventArgs> onHandle = delegate (object obj, LoginHandleEventArgs args)
			{
				//连接服务器
				if (!this.Agent.IsStarted)
				{
					Common.ConnectionServer conn = new Common.ConnectionServer(this.Agent);
					conn.Connection();
				}

				//发送数据
				if (this.Agent.IsStarted)
				{
					Common.Data.LoginUserName = args.UserName;
					Common.Data.LoginPassWord = args.PassWord;

					McsUtility.Models.LoginModel info = new McsUtility.Models.LoginModel
					{
						LoginName = Common.Data.LoginUserName,
						LoginPass = Common.Data.LoginPassWord
					};
					byte[] bytes = ProtocolHelper.WritePackage<McsUtility.Models.LoginModel>(ProtoType.MinerManagerLogin, info);
					this.Agent.AgentSend(bytes);
				}
				else
				{
					MessageBox.Show("服务器连接已断开，请检查网络是否畅通后重新登录。", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
					WriteStatusMessage("服务器连接已断开，请检查网络是否畅通后重新登录。");
				}
			};

			#endregion

			#region onCancel事件

			Action<object, EventArgs> onCancel = delegate (object obj, EventArgs args)
			{
				if (this.FormLogin != null)
				{
					this.FormLogin.Dispose();
					this.FormLogin = null;
				}
			};

			#endregion

			if (this.FormLogin == null)
			{
				this.FormLogin = new Forms.UserLogin();
				this.FormLogin.OnHandle += new EventHandler<LoginHandleEventArgs>(onHandle);
				this.FormLogin.OnCancel += new EventHandler<EventArgs>(onCancel);
				this.FormLogin.ShowDialog();
			}
			else
			{
				this.FormLogin.ShowDialog();
			}
		}

		#endregion

		private void TopMenu_User_Logout_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
		{
			this.Agent.Stop();
		}

		private void TopMenu_User_ForgotPassWord_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
		{
			Forms.UserForgotPassword form = new Forms.UserForgotPassword(this.Agent);
			form.ShowDialog();
		}

		private void TopMenu_User_ChangeStaff_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
		{
			Action<object, EventArgs> onSuccess = delegate (object obj, EventArgs args)
			{
				WriteStatusVersionMessage();
			};

			Forms.UserChangeStaff form = new Forms.UserChangeStaff(this.Agent);
			form.OnSuccess += new EventHandler<EventArgs>(onSuccess);
			form.ShowDialog();
		}

		private void TopMenu_Miner_Wallet_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
		{
			Action<object, EventArgs> onClose = delegate (object obj, EventArgs args)
			{
				LoadSearchData();
			};

			Forms.MinerWallet form = new Forms.MinerWallet(this.Agent);
			form.OnClose += new EventHandler<EventArgs>(onClose);
			form.ShowDialog();
		}

		#endregion

		#region MinerList按钮与事件

		#region void BtnCheckAll_Click(object sender, EventArgs e)

		private void BtnCheckAll_Click(object sender, EventArgs e)
		{
			List<Models.MinerModel> infosMiner = MinerList.DataSource as List<Models.MinerModel>;
			infosMiner.ForEach(info =>
			{
				info.Checked = true;
			});
			MinerList.RefreshDataSource();
		}

		#endregion

		#region void BtnCheckInverse_Click(object sender, EventArgs e)

		private void BtnCheckInverse_Click(object sender, EventArgs e)
		{
			List<Models.MinerModel> infosMiner = MinerList.DataSource as List<Models.MinerModel>;
			infosMiner.ForEach(info =>
			{
				info.Checked = !info.Checked;
			});
			MinerList.RefreshDataSource();
		}

		#endregion

		#region void BtnEditConfiguration_Click(object sender, EventArgs e)

		private void BtnEditConfiguration_Click(object sender, EventArgs e)
		{
			List<Models.MinerModel> infos = new List<Models.MinerModel>();

			List<Models.MinerModel> infosMiner = MinerList.DataSource as List<Models.MinerModel>;
			foreach (Models.MinerModel info in infosMiner)
			{
				if (info.Checked)
					infos.Add(info);
			}

			if (infos.Count > 0)
			{
				Action<object, ObjectEventArgs> onSuccess = delegate (object obj, ObjectEventArgs args)
				{
					if (MessageBox.Show("修改配置指令下达成功。", "成功", MessageBoxButtons.OK, MessageBoxIcon.Information) == DialogResult.OK)
					{
						Forms.MinerBatchConfiguration formConfiguration = obj as Forms.MinerBatchConfiguration;
						if (formConfiguration != null)
							formConfiguration.Close();
					}
				};

				Forms.MinerBatchConfiguration form = new Forms.MinerBatchConfiguration(this.Agent, infos);
				form.OnSuccess += new EventHandler<ObjectEventArgs>(onSuccess);
				form.ShowDialog();
			}
			else
			{
				MessageBox.Show("请选择要修改配置的矿机。", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
			}
		}

		#endregion

		#region void BtnMinerRestart_Click(object sender, EventArgs e)

		private void BtnMinerRestart_Click(object sender, EventArgs e)
		{
			//发送数据
			if (this.Agent.IsStarted)
			{
				if (MessageBox.Show("确定要批量重启已经选取的矿机吗？", "重启矿机", MessageBoxButtons.OKCancel, MessageBoxIcon.Question, MessageBoxDefaultButton.Button1) == DialogResult.OK)
				{
					List<Models.MinerModel> infosMiner = MinerList.DataSource as List<Models.MinerModel>;

					List<int> ids = new List<int>();
					infosMiner.ForEach(info =>
					{
						if (info.Checked)
							ids.Add(info.ID);
					});

					if (ids.Count > 0)
					{
						byte[] bytes = ProtocolHelper.WritePackage<int[]>(ProtoType.MinerManagerReset, ids.ToArray());
						this.Agent.AgentSend(bytes);
						MessageBox.Show("重启矿机指令下达成功。", "成功", MessageBoxButtons.OK, MessageBoxIcon.Information);
					}
					else
					{
						MessageBox.Show("请选择要重启的矿机。", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
					}
				}
			}
			else
			{
				MessageBox.Show("服务器连接已断开，请检查网络是否畅通后重新登录。", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
				WriteStatusMessage("服务器连接已断开，请检查网络是否畅通后重新登录。");
			}
		}

		#endregion

		#region void BtnMinerStart_Click(object sender, EventArgs e)

		private void BtnMinerStart_Click(object sender, EventArgs e)
		{
			//发送数据
			if (this.Agent.IsStarted)
			{
				if (MessageBox.Show("确定要将选取的矿机开始挖矿吗？", "开始挖矿", MessageBoxButtons.OKCancel, MessageBoxIcon.Question, MessageBoxDefaultButton.Button1) == DialogResult.OK)
				{
					List<Models.MinerModel> infosMiner = MinerList.DataSource as List<Models.MinerModel>;

					List<int> ids = new List<int>();
					infosMiner.ForEach(info =>
					{
						if (info.Checked)
							ids.Add(info.ID);
					});

					if (ids.Count > 0)
					{
						byte[] bytes = ProtocolHelper.WritePackage<int[]>(ProtoType.MinerManagerStartMining, ids.ToArray());
						this.Agent.AgentSend(bytes);
						MessageBox.Show("开始挖矿指令下达成功。", "成功", MessageBoxButtons.OK, MessageBoxIcon.Information);
					}
					else
					{
						MessageBox.Show("请选择要开始挖矿的矿机。", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
					}
				}
			}
			else
			{
				MessageBox.Show("服务器连接已断开，请检查网络是否畅通后重新登录。", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
				WriteStatusMessage("服务器连接已断开，请检查网络是否畅通后重新登录。");
			}
		}

		#endregion

		#region void BtnMinerStop_Click(object sender, EventArgs e)

		private void BtnMinerStop_Click(object sender, EventArgs e)
		{
			//发送数据
			if (this.Agent.IsStarted)
			{
				if (MessageBox.Show("确定要将选取的矿机停止挖矿吗？", "停止挖矿", MessageBoxButtons.OKCancel, MessageBoxIcon.Question, MessageBoxDefaultButton.Button1) == DialogResult.OK)
				{
					List<Models.MinerModel> infosMiner = MinerList.DataSource as List<Models.MinerModel>;

					List<int> ids = new List<int>();
					infosMiner.ForEach(info =>
					{
						if (info.Checked)
							ids.Add(info.ID);
					});

					if (ids.Count > 0)
					{
						byte[] bytes = ProtocolHelper.WritePackage<int[]>(ProtoType.MinerManagerEndMining, ids.ToArray());
						this.Agent.AgentSend(bytes);
						MessageBox.Show("停止挖矿指令下达成功。", "成功", MessageBoxButtons.OK, MessageBoxIcon.Information);
					}
					else
					{
						MessageBox.Show("请选择要停止挖矿的矿机。", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
					}
				}
			}
			else
			{
				MessageBox.Show("服务器连接已断开，请检查网络是否畅通后重新登录。", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
				WriteStatusMessage("服务器连接已断开，请检查网络是否畅通后重新登录。");
			}
		}

		#endregion

		#region void BtnMinerDelete_Click(object sender, EventArgs e)

		private void BtnMinerDelete_Click(object sender, EventArgs e)
		{
			//发送数据
			if (this.Agent.IsStarted)
			{
				if (MessageBox.Show("确定要删除选取的矿机吗？", "删除矿机", MessageBoxButtons.OKCancel, MessageBoxIcon.Question, MessageBoxDefaultButton.Button1) == DialogResult.OK)
				{
					List<Models.MinerModel> infosMiner = MinerList.DataSource as List<Models.MinerModel>;

					List<int> ids = new List<int>();
					infosMiner.ForEach(info =>
					{
						if (info.Checked)
							ids.Add(info.ID);
					});

					if (ids.Count > 0)
					{
						this.DeleteMinerIds = ids;
						byte[] bytes = ProtocolHelper.WritePackage<int[]>(ProtoType.MinerManagerDelMiner, ids.ToArray());
						this.Agent.AgentSend(bytes);
						MessageBox.Show("删除矿机指令下达成功。", "成功", MessageBoxButtons.OK, MessageBoxIcon.Information);
					}
					else
					{
						MessageBox.Show("请选择要删除的矿机。", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
					}
				}
			}
			else
			{
				MessageBox.Show("服务器连接已断开，请检查网络是否畅通后重新登录。", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
				WriteStatusMessage("服务器连接已断开，请检查网络是否畅通后重新登录。");
			}
		}

		#endregion

		#region void BtnLoadAllMiner_Click(object sender, EventArgs e)

		private void BtnLoadAllMiner_Click(object sender, EventArgs e)
		{
			Task.Factory.StartNew(() =>
			{
				for (int i = this.PageIndex; i <= this.PageCount; i++)
				{
					RequestMinerList(i, this.PageSize);
				}
				this.PageIndex = this.PageCount;
			});

			////发送数据
			//if (this.Agent.IsStarted)
			//{
			//	McsUtility.Models.MinersRequestModel sendInfo = new McsUtility.Models.MinersRequestModel
			//	{
			//		State = ((ComboboxListItem)SearchStatus.SelectedItem).Value.ConvertInt(-1),
			//		Currency = SearchCurrency.SelectedIndex >= 0 ? ((ComboboxListItem)SearchCurrency.SelectedItem).Value : "",
			//		OrePool = SearchPool.SelectedIndex >= 0 ? ((ComboboxListItem)SearchPool.SelectedItem).Value : "",
			//		Wallet = SearchWallet.SelectedIndex >= 0 ? ((ComboboxListItem)SearchWallet.SelectedItem).Value : "",
			//	};

			//	byte[] bytes = ProtocolHelper.WritePackage<McsUtility.Models.MinersRequestModel>(ProtoType.MinerManagerGetMinersAll, sendInfo);
			//	this.Agent.AgentSend(bytes);
			//}
			//else
			//{
			//	MessageBox.Show("服务器连接已断开，请检查网络是否畅通后重新登录。", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
			//	WriteStatusMessage("服务器连接已断开，请检查网络是否畅通后重新登录。");
			//}
		}

		#endregion

		#region void MinerList_MouseClick(object sender, MouseEventArgs e)

		private void MinerList_MouseClick(object sender, MouseEventArgs e)
		{
			DevExpress.XtraGrid.Views.Grid.ViewInfo.GridHitInfo view = MinerListGridView.CalcHitInfo(e.Location);
			
			if (e.Button == MouseButtons.Left)
			{
				var column = MinerListGridView.FocusedColumn;
				if (column.Name.Equals("MinerList_Check"))
				{
					List<Models.MinerModel> infos = MinerList.DataSource as List<Models.MinerModel>;
					if (infos != null)
					{
						Models.MinerModel info = infos[MinerListGridView.FocusedRowHandle];
						info.Checked = !info.Checked;
						MinerList.RefreshDataSource();
					}
				}
			}

			if (e.Button == MouseButtons.Right && view.InRow)
			{
				var column = MinerListGridView.FocusedColumn;
				switch (column.Name.ToLower())
				{
					case "minerlist_firstwallet":
						this.RightContextMenu.Items[0].Visible = true;
						this.RightContextMenu.Items[0].Text = "复制主币钱包";
						break;
					case "minerlist_firstpool":
						this.RightContextMenu.Items[0].Visible = true;
						this.RightContextMenu.Items[0].Text = "复制主币矿池";
						break;
					case "minerlist_secondwallet":
						this.RightContextMenu.Items[0].Visible = true;
						this.RightContextMenu.Items[0].Text = "复制辅币钱包";
						break;
					default:
						this.RightContextMenu.Items[0].Visible = false;
						break;
				}

				this.RightContextMenu.Show(MinerList, e.Location);
			}
		}

		#endregion

		#region void MinerList_MouseDoubleClick(object sender, MouseEventArgs e)

		private void MinerList_MouseDoubleClick(object sender, MouseEventArgs e)
		{
			DevExpress.XtraGrid.Views.Grid.ViewInfo.GridHitInfo view = MinerListGridView.CalcHitInfo(e.Location);

			if (e.Button == MouseButtons.Left && view.InRow)
			{
				Models.MinerModel miner = (Models.MinerModel)view.RowInfo.RowKey;

				//打开窗体
				if (miner != null)
				{
					Action<object, EventArgs> onClose = delegate (object obj, EventArgs args)
					{
						this.AllowRefreshHashrate = true;
					};

					this.AllowRefreshHashrate = false;
					Forms.MinerHashrate form = new Forms.MinerHashrate(this.Agent, miner.ID, miner.MinerName, miner.FirstCoin, miner.SecondCoin);
					form.OnClose += new EventHandler<EventArgs>(onClose);
					form.ShowDialog();
				}
			}
		}

		#endregion

		#region void ItemDisplayLog_CheckedChanged(object sender, EventArgs e)

		private void ItemDisplayLog_CheckedChanged(object sender, EventArgs e)
		{
			if (ItemDisplayLog.Checked)
			{
				if (!GroupBoxLog.Visible)
				{
					GroupBoxLog.Visible = true;
					GroupBoxMiner.Height -= GroupBoxLog.Height;
				}
			}
			else
			{
				if (GroupBoxLog.Visible)
				{
					GroupBoxLog.Visible = false;
					GroupBoxMiner.Height += GroupBoxLog.Height;
				}
			}
		}

		#endregion

		#region void MinerListGridView_RowCellStyle(object sender, DevExpress.XtraGrid.Views.Grid.RowCellStyleEventArgs e)

		private void MinerListGridView_RowCellStyle(object sender, DevExpress.XtraGrid.Views.Grid.RowCellStyleEventArgs e)
		{
			var stateColumn = MinerListGridView.Columns.FirstOrDefault(p => p.Name == "MinerList_StateName");
			if (stateColumn != null && e.Column.VisibleIndex == stateColumn.VisibleIndex)
			{
				List<Models.MinerModel> infos = MinerList.DataSource as List<Models.MinerModel>;
				if (infos != null)
				{
					Models.MinerModel info = infos[e.RowHandle];
					switch (info.State)
					{
						case 0: e.Appearance.ForeColor = Color.FromArgb(0, 0, 0); break;
						case 1: e.Appearance.ForeColor = Color.FromArgb(34, 199, 165); break;
						case 2: e.Appearance.ForeColor = Color.FromArgb(21, 181, 243); break;
					}
				}
			}
		}

		#endregion

		#region void MinerListGridView_TopRowChanged(object sender, EventArgs e)

		private void MinerListGridView_TopRowChanged(object sender, EventArgs e)
		{
			WaterfallRequestMinerList();
		}

		#endregion

		#endregion

		#region void BtnSearch_Click(object sender, EventArgs e)

		private void BtnSearch_Click(object sender, EventArgs e)
		{
			ClearMinerList();

			this.PageIndex = 1;
			RequestMinerList(this.PageIndex, this.PageSize);
		}

		#endregion

		#region void BtnClearMinerStatusLog_Click(object sender, EventArgs e)

		private void BtnClearMinerStatusLog_Click(object sender, EventArgs e)
		{
			MinerStatusLog.Text = "";
			System.IO.File.WriteAllText(Utility.MinerStatusLogPath, "", Encoding.UTF8);
		}

		#endregion

		#region void SearchCurrency_SelectedIndexChanged(object sender, EventArgs e)

		private void SearchCurrency_SelectedIndexChanged(object sender, EventArgs e)
		{
			ComboboxListItem item = SearchCurrency.SelectedItem as ComboboxListItem;
			if (item != null && !string.IsNullOrWhiteSpace(item.Value))
			{
				McsUtility.Models.CurrencysModel info = Common.Data.UserCurrency.Where(p => p.Name.Equals(item.Value, StringComparison.CurrentCultureIgnoreCase)).FirstOrDefault();
				if (info != null)
				{
					//钱包信息
					List<ComboboxListItem> itemsWallet = new List<ComboboxListItem>
						{
							new ComboboxListItem("全部", "")
						};

					//矿池信息
					List<ComboboxListItem> itemsPool = new List<ComboboxListItem>
						{
							new ComboboxListItem("全部", "")
						};

					foreach (McsUtility.Models.WalletsModel infoWallet in info.Wallets)
					{
						itemsWallet.Add(new ComboboxListItem(infoWallet.Address, infoWallet.Address));
					}

					foreach (McsUtility.Models.WalletsModel infoPool in info.OrePools)
					{
						itemsPool.Add(new ComboboxListItem(!string.IsNullOrWhiteSpace(infoPool.Remark) ? infoPool.Remark : infoPool.Address, infoPool.Address));
					}

					Utility.Forms.SetComboBoxEdit(this, "SearchWallet", itemsWallet);
					Utility.Forms.SetComboBoxEdit(this, "SearchPool", itemsPool);
				}
			}
			else
			{
				Utility.Forms.SetComboBoxEdit(this, "SearchWallet", new List<ComboboxListItem> { new ComboboxListItem("全部", "") });
				Utility.Forms.SetComboBoxEdit(this, "SearchPool", new List<ComboboxListItem> { new ComboboxListItem("全部", "") });
			}
		}

		#endregion

		//----------------------------------------------------------------------

		#region void SetControlStatus(bool isLogin) 设置控件在不同登录状态时的显示方式。

		private delegate void DelegateSetControlStatus(bool isLogin);

		/// <summary>
		/// 设置控件在不同登录状态时的显示方式。
		/// </summary>
		/// <param name="isLogin"></param>
		private void SetControlStatus(bool isLogin)
		{
			if (this.InvokeRequired)
			{
				DelegateSetControlStatus d = new DelegateSetControlStatus(SetControlStatus);
				this.BeginInvoke(d, isLogin);
			}
			else
			{
				if (isLogin)
				{
					TopMenu_User_Register.Visibility = DevExpress.XtraBars.BarItemVisibility.Never;
					TopMenu_User_Login.Visibility = DevExpress.XtraBars.BarItemVisibility.Never;
					TopMenu_User_Logout.Visibility = DevExpress.XtraBars.BarItemVisibility.Always;
					TopMenu_User_ForgotPassWord.Visibility = DevExpress.XtraBars.BarItemVisibility.Always;
					TopMenu_User_ChangeStaff.Enabled = true;
					TopMenu_Miner_Wallet.Enabled = true;

					BtnSearch.Enabled = true;
					SearchCurrency.Enabled = true;
					SearchWallet.Enabled = true;
					SearchPool.Enabled = true;
					SearchStatus.Enabled = true;

					BtnCheckAll.Enabled = true;
					BtnCheckInverse.Enabled = true;
					BtnEditConfiguration.Enabled = true;
					BtnMinerRestart.Enabled = true;
					BtnMinerStart.Enabled = true;
					BtnMinerStop.Enabled = true;
					BtnMinerDelete.Enabled = true;
					//BtnStatusInfo.Enabled = true;

					//BtnFirstPage.Enabled = true;
					//BtnBeforPage.Enabled = true;
					//BtnAfterPage.Enabled = true;
					//BtnLastPage.Enabled = true;

					this.AllowRefreshHashrate = true;
					this.PageIndex = 1;

					WriteStatusMessage("");
					WriteStatusVersionMessage();
					LoadSearchData();
					RequestMinerList(1, this.PageSize);
				}
				else
				{
					TopMenu_User_Register.Visibility = DevExpress.XtraBars.BarItemVisibility.Always;
					TopMenu_User_Login.Visibility = DevExpress.XtraBars.BarItemVisibility.Always;
					TopMenu_User_Logout.Visibility = DevExpress.XtraBars.BarItemVisibility.Never;
					TopMenu_User_ForgotPassWord.Visibility = DevExpress.XtraBars.BarItemVisibility.Never;
					TopMenu_User_ChangeStaff.Enabled = false;
					TopMenu_Miner_Wallet.Enabled = false;

					BtnSearch.Enabled = false;
					SearchCurrency.Enabled = false;
					SearchWallet.Enabled = false;
					SearchPool.Enabled = false;
					SearchStatus.Enabled = false;

					BtnCheckAll.Enabled = false;
					BtnCheckInverse.Enabled = false;
					BtnEditConfiguration.Enabled = false;
					BtnMinerRestart.Enabled = false;
					BtnMinerStart.Enabled = false;
					BtnMinerStop.Enabled = false;
					BtnMinerDelete.Enabled = false;
					//BtnStatusInfo.Enabled = false;
					//PageMessage.Text = "";

					//BtnFirstPage.Enabled = false;
					//BtnBeforPage.Enabled = false;
					//BtnAfterPage.Enabled = false;
					//BtnLastPage.Enabled = false;

					this.AllowRefreshHashrate = false;

					MinerCountMessage.Text = "";
					WriteStatusMessage("请先登录系统后再进行相关操作");
					WriteStatusLoginMessage("未登录");

					ClearSearchData();
					ClearMinerList();
				}
			}
		}

		#endregion

		#region void WriteStatusMessage(string message) 写入状态栏信息。

		private delegate void DelegateWriteStatusMessage(string message);

		/// <summary>
		/// 写入状态栏信息。
		/// </summary>
		/// <param name="message"></param>
		private void WriteStatusMessage(string message)
		{
			if (this.InvokeRequired)
			{
				DelegateWriteStatusMessage d = new DelegateWriteStatusMessage(WriteStatusMessage);
				this.BeginInvoke(d, message);
			}
			else
			{
				BottomStatus_Message.Caption = message;
			}
		}

		#endregion

		#region void WriteStatusLoginMessage(string message) 写入状态栏登录信息。

		private delegate void DelegateWriteStatusLoginMessage(string message);

		/// <summary>
		/// 写入状态栏登录信息。
		/// </summary>
		/// <param name="message"></param>
		private void WriteStatusLoginMessage(string message)
		{
			if (this.InvokeRequired)
			{
				DelegateWriteStatusLoginMessage d = new DelegateWriteStatusLoginMessage(WriteStatusLoginMessage);
				this.BeginInvoke(d, message);
			}
			else
			{
				BottomStatus_LoginMessage.Caption = message;
			}
		}

		#endregion

		#region void WriteStatusVersionMessage() 写入状态栏版本信息。

		private delegate void DelegateWriteStatusVersionMessage();

		/// <summary>
		/// 写入状态栏版本信息。
		/// </summary>
		private void WriteStatusVersionMessage()
		{
			if (this.InvokeRequired)
			{
				DelegateWriteStatusVersionMessage d = new DelegateWriteStatusVersionMessage(WriteStatusVersionMessage);
				this.BeginInvoke(d);
			}
			else
			{
				string staffName = string.Empty;

				if (!string.IsNullOrWhiteSpace(Common.Data.Staff.Name))
					staffName += "客户经理：" + Common.Data.Staff.Name;

				if (!string.IsNullOrWhiteSpace(Common.Data.Staff.QQ1))
				{
					staffName += !string.IsNullOrWhiteSpace(staffName) ? " " : "";
					staffName += "QQ：" + Common.Data.Staff.QQ1;
				}

				if (!string.IsNullOrWhiteSpace(Common.Data.Staff.WeiXin1))
				{
					staffName += !string.IsNullOrWhiteSpace(staffName) ? " " : "";
					staffName += "微信：" + Common.Data.Staff.WeiXin1;
				}

				BottomStatus_Version.Caption = (!string.IsNullOrWhiteSpace(staffName) ? staffName + " " : "") + Utility.SoftName + " " + Utility.Version;
			}
		}

		#endregion

		#region void WriteMinerStatusLog(string msg) 写入矿机状态日志。

		private delegate void DelegateWriteMinerStatusLog(DateTime dTime, string msg);

		/// <summary>
		/// 写入矿机状态日志。
		/// </summary>
		/// <param name="msg"></param>
		private void WriteMinerStatusLog(DateTime dTime, string msg)
		{
			if (this.InvokeRequired)
			{
				DelegateWriteMinerStatusLog d = new DelegateWriteMinerStatusLog(WriteMinerStatusLog);
				this.BeginInvoke(d, dTime, msg);
			}
			else
			{
				string logMsg = string.Empty;
				logMsg += !string.IsNullOrWhiteSpace(MinerStatusLog.Text) ? Environment.NewLine : "";
				logMsg += dTime.ToString("HH:mm:ss") + " " + msg;

				MinerStatusLog.Text += logMsg;
				MinerStatusLog.Select(MinerStatusLog.Text.Length, 0);
				MinerStatusLog.ScrollToCaret();

				System.IO.File.AppendAllText(Utility.MinerStatusLogPath, logMsg, Encoding.UTF8);
			}
		}

		#endregion

		#region void LoadSearchData() 加载搜索项。

		/// <summary>
		/// 加载搜索项。
		/// </summary>
		private void LoadSearchData()
		{
			//币种信息
			List<ComboboxListItem> itemsCurrency = new List<ComboboxListItem>();
			itemsCurrency.Add(new ComboboxListItem("全部", ""));
			foreach (McsUtility.Models.CurrencysModel info in Common.Data.UserCurrency)
			{
				itemsCurrency.Add(new ComboboxListItem(info.Remark, info.Name));
			}
			Utility.Forms.SetComboBoxEdit(this, "SearchCurrency", itemsCurrency);
		}

		#endregion

		#region void ClearSearchData() 清空搜索项。

		/// <summary>
		/// 清空搜索项。
		/// </summary>
		private void ClearSearchData()
		{
			Utility.Forms.SetComboBoxEdit(this, "SearchCurrency", new List<ComboboxListItem>());
			Utility.Forms.SetComboBoxEdit(this, "SearchWallet", new List<ComboboxListItem>());
			Utility.Forms.SetComboBoxEdit(this, "SearchPool", new List<ComboboxListItem>());
		}

		#endregion

		#region void RequestMinerList(int pageIndex, int pageSize) 请求矿机列表。

		private delegate void DelegateRequestMinerList(int pageIndex, int pageSize);

		/// <summary>
		/// 请求矿机列表。
		/// </summary>
		private void RequestMinerList(int pageIndex, int pageSize)
		{
			if (this.InvokeRequired)
			{
				DelegateRequestMinerList d = new DelegateRequestMinerList(RequestMinerList);
				this.BeginInvoke(d, pageIndex, PageSize);
			}
			else
			{
				//发送数据
				if (this.Agent.IsStarted)
				{
					int number = pageSize % 10 > 0 ? pageSize / 10 + 1 : pageSize / 10;
					for (int i = 1; i <= number; i++)
					{
						McsUtility.Models.MinersRequestModel info = new McsUtility.Models.MinersRequestModel
						{
							State = ((ComboboxListItem)SearchStatus.SelectedItem).Value.ConvertInt(-1),
							Currency = SearchCurrency.SelectedIndex >= 0 ? ((ComboboxListItem)SearchCurrency.SelectedItem).Value : "",
							OrePool = SearchPool.SelectedIndex >= 0 ? ((ComboboxListItem)SearchPool.SelectedItem).Value : "",
							Wallet = SearchWallet.SelectedIndex >= 0 ? ((ComboboxListItem)SearchWallet.SelectedItem).Value : "",
							PageIndex = pageIndex > 1 ? (pageIndex - 1) * 2 + i : pageIndex + i - 1,
							PageRows = 10
						};
						byte[] bytes = ProtocolHelper.WritePackage<McsUtility.Models.MinersRequestModel>(ProtoType.MinerManagerGetMiners, info);
						this.Agent.AgentSend(bytes);
					}
				}
				else
				{
					MessageBox.Show("服务器连接已断开，请检查网络是否畅通后重新登录。", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
					WriteStatusMessage("服务器连接已断开，请检查网络是否畅通后重新登录。");
				}
			}
		}

		#endregion

		#region void WaterfallRequestMinerList() 瀑布请求矿机列表。
		
		/// <summary>
		/// 瀑布请求矿机列表。
		/// </summary>
		private void WaterfallRequestMinerList()
		{
			if (!this.WaterfallRequestingMinerList)
				this.WaterfallRequestingMinerList = true;
			else
				return;

			List<Models.MinerModel> infos = MinerList.DataSource as List<Models.MinerModel>;
			if (infos != null)
			{
				if (MinerListGridView.IsRowVisible(infos.Count - 5) == DevExpress.XtraGrid.Views.Grid.RowVisibleState.Visible)
				{
					if (this.PageIndex < this.PageCount)
					{
						this.PageIndex += 1;
						this.PageIndex = this.PageIndex <= this.PageCount ? this.PageIndex : this.PageCount;

						RequestMinerList(this.PageIndex, this.PageSize);
					}
					else
					{
						this.WaterfallRequestingMinerList = false;
					}
				}
				else
				{
					this.WaterfallRequestingMinerList = false;
				}
			}
			else
			{
				this.WaterfallRequestingMinerList = false;
			}
		}

		#endregion

		#region void LoadMinerList(List<McsUtility.Models.MinersModel> infos) 加载矿机列表。

		private delegate void DelegateLoadMinerList(List<Models.MinerModel> infos);

		/// <summary>
		/// 加载矿机列表。
		/// </summary>
		/// <param name="infos"></param>
		private void LoadMinerList(List<Models.MinerModel> infos)
		{
			if (this.InvokeRequired)
			{
				DelegateLoadMinerList d = new DelegateLoadMinerList(LoadMinerList);
				this.BeginInvoke(d, infos);
			}
			else
			{
				MinerList.DataSource = infos;
				WaterfallRequestMinerList();
				MinerCountMessage.Text = string.Format("共有矿机{0}台，当前显示{1}台。", this.TotalCount, infos.Count);
			}
		}

		#endregion

		#region void InsertMinerList(List<Models.MinerModel> infos) 在矿机列表底部插入矿机数据。

		private delegate void DelegateInsertMinerList(List<Models.MinerModel> infos);

		/// <summary>
		/// 在矿机列表底部插入矿机数据。
		/// </summary>
		/// <param name="infos"></param>
		private void InsertMinerList(List<Models.MinerModel> infos)
		{
			if (this.InvokeRequired)
			{
				DelegateInsertMinerList d = new DelegateInsertMinerList(InsertMinerList);
				this.BeginInvoke(d, infos);
			}
			else
			{
				List<Models.MinerModel> infosMiner = MinerList.DataSource as List<Models.MinerModel>;
				if (infosMiner == null)
					infosMiner = new List<Models.MinerModel>();

				infos.ForEach(info =>
				{
					int index = infosMiner.FindIndex(p => p.ID == info.ID);
					if (index < 0)
						infosMiner.Add(info);
				});
				
				MinerList.DataSource = infosMiner;
				WaterfallRequestMinerList();
				MinerCountMessage.Text = string.Format("共有矿机{0}台，当前显示{1}台。", this.TotalCount, infosMiner.Count);
			}
		}

		#endregion

		#region void UpdateMinerState(int minerId, int state) 更新矿机列表中的状态。

		private delegate void DelegateUpdateMinerState(int minerId, int state);

		/// <summary>
		/// 更新矿机列表中的状态。
		/// </summary>
		/// <param name="minerId">矿机Id</param>
		/// <param name="state">状态</param>
		private void UpdateMinerState(int minerId, int state)
		{
			if (this.InvokeRequired)
			{
				DelegateUpdateMinerState d = new DelegateUpdateMinerState(UpdateMinerState);
				this.BeginInvoke(d, minerId, state);
			}
			else
			{
				List<Models.MinerModel> infosMiner = MinerList.DataSource as List<Models.MinerModel>;
				if (infosMiner == null) return;

				int index = infosMiner.FindIndex(p => p.ID == minerId);
				if (index >= 0)
				{
					infosMiner[index].State = state;

					if (state != 2)
					{
						infosMiner[index].FirstHashrate = string.Empty;
						infosMiner[index].SecondHashrate = string.Empty;
					}

					MinerList.RefreshDataSource();
				}
			}
		}

		#endregion

		#region void UpdateMinerModel(int minerId, Models.MinerModel info) 更新矿机信息。

		private delegate void DelegateUpdateMinerModel(int minerId, Models.MinerModel info);

		/// <summary>
		/// 更新矿机信息。
		/// </summary>
		/// <param name="minerId">矿机Id</param>
		/// <param name="info">矿机信息</param>
		private void UpdateMinerModel(int minerId, Models.MinerModel info)
		{
			if (this.InvokeRequired)
			{
				DelegateUpdateMinerModel d = new DelegateUpdateMinerModel(UpdateMinerModel);
				this.BeginInvoke(d, minerId, info);
			}
			else
			{
				List<Models.MinerModel> infosMiner = MinerList.DataSource as List<Models.MinerModel>;
				if (infosMiner == null) return;

				int index = infosMiner.FindIndex(p => p.ID == minerId);
				if (index >= 0)
				{
					infosMiner[index] = info;
					MinerList.RefreshDataSource();
				}
			}
		}

		#endregion

		#region void DeleteMinerModel(List<int> minerIds) 删除矿机信息。

		private delegate void DelegateDeleteMinerModel(List<int> minerIds);

		/// <summary>
		/// 删除矿机信息。
		/// </summary>
		/// <param name="minerId"></param>
		private void DeleteMinerModel(List<int> minerIds)
		{
			if (this.InvokeRequired)
			{
				DelegateDeleteMinerModel d = new DelegateDeleteMinerModel(DeleteMinerModel);
				this.BeginInvoke(d, minerIds);
			}
			else
			{
				List<Models.MinerModel> infosMiner = MinerList.DataSource as List<Models.MinerModel>;
				if (infosMiner == null) return;

				if (minerIds.Count > 0)
				{
					minerIds.ForEach(id =>
					{
						int index = infosMiner.FindIndex(p => p.ID == id);
						if (index >= 0)
							infosMiner.RemoveAt(index);
					});
					
					MinerList.DataSource = infosMiner;
					MinerList.RefreshDataSource();
				}
			}
		}

		#endregion

		#region void RequestMinerHashrate() 请求矿机列表中的算力信息。

		private delegate void DelegateRequestMinerHashrate();

		/// <summary>
		/// 请求矿机列表中的算力信息。
		/// </summary>
		private void RequestMinerHashrate()
		{
			if (this.InvokeRequired)
			{
				DelegateRequestMinerHashrate d = new DelegateRequestMinerHashrate(RequestMinerHashrate);
				this.BeginInvoke(d);
			}
			else
			{
				List<Models.MinerModel> infosMiner = MinerList.DataSource as List<Models.MinerModel>;
				if (infosMiner != null)
				{
					List<int> ids = new List<int>();
					for (int i = 0; i < infosMiner.Count; i++)
					{
						ids.Add(infosMiner[i].ID);

						if (ids.Count >= 10)
						{
							byte[] bytes = ProtocolHelper.WritePackage<int[]>(ProtoType.MinerManagerGetRedisData, ids.ToArray());
							this.Agent.AgentSend(bytes);

							ids = new List<int>();
						}
					}

					if (ids.Count > 0)
					{
						byte[] bytes = ProtocolHelper.WritePackage<int[]>(ProtoType.MinerManagerGetRedisData, ids.ToArray());
						this.Agent.AgentSend(bytes);
					}
				}
			}
		}

		#endregion

		#region void LoadMinerHashrate(List<McsUtility.Models.RedisDataModel> infos) 读取并在矿机列表中显示算力。

		private delegate void DelegateLoadMinerHashrate(List<McsUtility.Models.RedisDataModel> infos);

		/// <summary>
		/// 读取并在矿机列表中显示算力。
		/// </summary>
		/// <param name="infos"></param>
		private void LoadMinerHashrate(List<McsUtility.Models.RedisDataModel> infos)
		{
			if (this.InvokeRequired)
			{
				DelegateLoadMinerHashrate d = new DelegateLoadMinerHashrate(LoadMinerHashrate);
				this.BeginInvoke(d, infos);
			}
			else
			{
				List<Models.MinerModel> infosMiner = MinerList.DataSource as List<Models.MinerModel>;
				if (infosMiner != null)
				{
					foreach(Models.MinerModel infoMiner in infosMiner)
					{
						int index = infos.FindIndex(p => p.MinerID == infoMiner.ID);
						if (index >= 0 && !string.IsNullOrWhiteSpace(infos[index].RedisData) && infoMiner.State == 2)
						{
							Models.MinerRedisData infoRedis = TomNet.Utility.Data.JsonHelper.FromJson<Models.MinerRedisData>(infos[index].RedisData);
							Models.MinerHashrateAndTmpFanModel infoHashrate = infoRedis.ConvertHashrate();
							infoMiner.FirstHashrate = infoHashrate.FirstTotalHashrate;
							infoMiner.SecondHashrate = infoHashrate.SecondTotalHashrate;
							infoMiner.FanAvg = infoHashrate.FanAvg;
							infoMiner.TempAvg = infoHashrate.TempAvg;
						}
					}
				}

				MinerList.RefreshDataSource();

				//设置计数器未执行刷新算力
				this.TimerRefreshingHashrate = false;
			}
		}

		#endregion

		#region void ClearMinerList() 清空矿机列表中的矿机信息。

		private delegate void DelegateClearMinerList();

		/// <summary>
		/// 清空矿机列表中的矿机信息。
		/// </summary>
		private void ClearMinerList()
		{
			if (this.InvokeRequired)
			{
				DelegateClearMinerList d = new DelegateClearMinerList(ClearMinerList);
				this.BeginInvoke(d);
			}
			else
			{
				MinerList.DataSource = "";
				MinerCountMessage.Text = "";
			}
		}

		#endregion

		#region void OpenFormReconnect() 打开掉线重连窗体。

		private delegate void DelegateOpenFormReconnect();

		/// <summary>
		/// 打开掉线重连窗体。
		/// </summary>
		private void OpenFormReconnect()
		{
			if (this.InvokeRequired)
			{
				DelegateOpenFormReconnect d = new DelegateOpenFormReconnect(OpenFormReconnect);
				this.BeginInvoke(d);
			}
			else
			{
				//关闭打开的窗体
				List<string> names = new List<string>();
				foreach (Form form in Application.OpenForms)
				{
					if (form.Name != this.Name)
						names.Add(form.Name);
				}

				foreach (string name in names)
				{
					Application.OpenForms[name].Close();
				}

				#region onHandle事件

				Action<object, EventArgs> onHandle = delegate (object obj, EventArgs args)
				{
					this.Agent = new Common.AgentComponent();
					InitAgent();

					//连接服务器
					Common.ConnectionServer conn = new Common.ConnectionServer(this.Agent);
					bool isStarted = conn.Connection();
					if (isStarted)
					{
						McsUtility.Models.LoginModel info = new McsUtility.Models.LoginModel
						{
							LoginName = Common.Data.LoginUserName,
							LoginPass = Common.Data.LoginPassWord
						};
						byte[] bytes = ProtocolHelper.WritePackage<McsUtility.Models.LoginModel>(ProtoType.MinerManagerLogin, info);
						this.Agent.AgentSend(bytes);

						this.FormReconnect.HandleFeedback(true);
					}
					else
					{
						Forms.Reconnect formReconnect = (Forms.Reconnect)obj;
						formReconnect.HandleFeedback(false);
					}
				};

				#endregion

				#region onCancel事件

				Action<object, EventArgs> onCancel = delegate (object obj, EventArgs args)
				{
					if (this.FormReconnect != null)
					{
						this.FormReconnect.Dispose();
						this.FormReconnect = null;
					}
				};

				#endregion

				if (this.FormReconnect == null)
				{
					this.FormReconnect = new Forms.Reconnect();
					this.FormReconnect.Owner = this;
					this.FormReconnect.OnHandle += new EventHandler<EventArgs>(onHandle);
				}

				if (!this.Agent.IsStarted && !this.FormReconnect.Visible)
				{
					this.FormReconnect.ShowDialog();
				}
			}
		}

		#endregion
		
		#region void OpenPopup(string title, string msg) 打开弹出框。

		/// <summary>
		/// 打开弹出框。
		/// </summary>
		/// <param name="title">标题</param>
		/// <param name="msg">提示信息</param>
		private void OpenPopup(string title, string msg)
		{
			DevExpress.XtraBars.Alerter.AlertInfo info = new DevExpress.XtraBars.Alerter.AlertInfo(title, Environment.NewLine + msg + Environment.NewLine + Environment.NewLine);
			info.Image = Properties.Resources.exclamation;
			PopupArticle.Show(this, info);

			System.Media.SoundPlayer simpleSound = new System.Media.SoundPlayer(Properties.Resources.ResourceManager.GetStream("msg"));
			simpleSound.Play();
		}

		#endregion
	}
}
